
package VisAVisTab;


import com.hp.hpl.jena.ontology.*;
import java.util.*;
import javax.swing.tree.*;

/**
 * This class shows a tree representation of the property hierarchy of the ontology opened
 */
public class PropertyHierarchy{
    
    DefaultMutableTreeNode rootNode;
    public DefaultTreeModel treeModel ;
    OntModel model;
    
    
    public PropertyHierarchy(){
    }
    
    
    /** Show the sub-property hierarchy encoded by the given model */
    public void showHierarchy(OntModel m ) {
        model=m;
        
        Iterator objit=m.listObjectProperties();
        Iterator datait=m.listDatatypeProperties();
        Iterator propit=m.listOntProperties();
        
        //add a default root node for the properties JTree
        NodeInfo rootInfo;
        
        rootInfo=new NodeInfo(NodeInfo.OTHER,"Root",null,null);
        rootNode = new DefaultMutableTreeNode(rootInfo);
        treeModel= new DefaultTreeModel(rootNode) ;
      
         //recurse down to the sub-properties,calling method showProperty for properties that are not sub-properties for other properties
        for (Iterator i = rootProperties( m );  i.hasNext();  ) {
            showProperty((OntProperty) i.next(),rootNode, new ArrayList() );
        }
        
    }
    
    

    
    /** Present a property, then recurse down to the sub-properties.
     *  Use occurs check to prevent getting stuck in a loop
     */
    protected void showProperty(OntProperty prop, DefaultMutableTreeNode parentNode, List occurs ) {
        
        
         /** find the direct sub-properties,super-properties,inverse properties
         *range and domain of the given property,in order to create and fill a new structure PropertyInfo
         * which will be added to the tree
         */
        int type=PropertyInfo.OTHER;
        if (prop.isDatatypeProperty()) type=PropertyInfo.DATAT_PROPERTY;
        else if (prop.isObjectProperty()) type=PropertyInfo.OBJ_PROPERTY;
        //else if (currentProp.isAnnotationProperty()) type=PropertyInfo.ANNOT_PROPERTY;
        
        Iterator isubp=prop.listSubProperties(true);
        Vector subproperties=new Vector();
        while (isubp.hasNext()){
            subproperties.addElement((OntProperty)isubp.next());
        }
        
        Iterator isuperp=prop.listSuperProperties(true);
        Vector superproperties=new Vector();
        while (isuperp.hasNext()){
            superproperties.addElement((OntProperty)isuperp.next());
        }
        
        Iterator irange=prop.listRange();
        Vector range=new Vector();
        while (irange.hasNext()){
            range.addElement((OntResource)irange.next());
        }
        
        /*find the domain of a property,even when it is defined as the union of multiple classes
         */
        Iterator idomain=prop.listDomain();
        Vector domain=new Vector();
        while (idomain.hasNext()){
            OntClass current =(OntClass)idomain.next();
            if (!current.isAnon()) domain.addElement(current);
            else{
                if (current.isUnionClass()) {
                    UnionClass uc=current.asUnionClass();
                    Iterator oper=uc.listOperands();
                    while (oper.hasNext()) domain.addElement((OntClass)oper.next());
                }
            }
        }
        
        Iterator iinv=prop.listInverse();
        Vector inverse=new Vector();
        while (iinv.hasNext()){
            inverse.addElement((OntProperty)iinv.next());
        }
        
        
        PropertyInfo nodeInfo=new PropertyInfo(prop.getURI(),type,subproperties,superproperties,range,domain,inverse);
        NodeInfo myInfo=new NodeInfo(NodeInfo.PROPERTY,prop.getURI(),null,nodeInfo);
        DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(myInfo);
        treeModel.insertNodeInto(childNode, parentNode, parentNode.getChildCount());
        
        
        
        
        
        // recurse to the next level down
        if (prop.canAs( OntProperty.class )  &&  !occurs.contains( prop )) {
            for (Iterator i = prop.listSubProperties(true );  i.hasNext(); ) {
                OntProperty sub = (OntProperty) i.next();
                
                // we push this expression on the occurs list before we recurse
                occurs.add( prop);
                showProperty(sub,childNode, occurs );
                occurs.remove(prop );
            }
        }
        
    }
    
    
    
    /**
     * Answer an iterator over the properties we will use as the roots of the depicted
     * hierarchy. 
     * @param m A model
     * @return An iterator over the named property hierarchy roots in m
     */
    protected Iterator rootProperties( OntModel m ) {
        List roots = new ArrayList();
        
        Iterator objit=m.listObjectProperties();
        Iterator datait=m.listDatatypeProperties();
        Iterator propit=m.listOntProperties();
        //Iterator annotit=m.listAnnotationProperties();
        
        Vector allProperties=new Vector();
        
        while(objit.hasNext()) allProperties.addElement((ObjectProperty)objit.next());
        while(datait.hasNext()) allProperties.addElement((DatatypeProperty)datait.next());
        while(propit.hasNext()) allProperties.addElement((OntProperty)propit.next());
        //while(annotit.hasNext()) allProperties.addElement((AnnotationProperty)annotit.next());
        
        
        for (int i =0;  i<allProperties.size();i++ ) {
            OntResource r = (OntResource) allProperties.elementAt(i);
            //if the property doesn't have a subproperty-of tag,add it to the roots Vector
            if (r.getCardinality( m.getProfile().SUB_PROPERTY_OF() ) == 0 ) roots.add(r); 
        }
        return roots.iterator();
    }
    
    
    
}




/*A class that contains all the information for a certain property
 **/

class PropertyInfo extends Object {
    
    public PropertyInfo(String text, int type,Vector vsub, Vector vsuper, Vector range,Vector domain,Vector inverse) {
        name = text;        //the name of the property
        this.type = type;   //can be either Object,Datatype, Annotation or other
        subProperties=vsub; //subproperties
        superProperties=vsuper; //superproperties
        this.range=range;       //range 
        this.domain=domain;     //domain
        this.inverse=inverse;   //inverse properties
        
    }
    
    
    public String toString() {
        return name;
    }
    
    public String name;
    public int type;
    public Vector subProperties;
    public Vector superProperties;
    public Vector range;
    public Vector domain;
    public Vector inverse;
    

    
    public static final int OBJ_PROPERTY = 100;
    public static final int DATAT_PROPERTY = 101;
    public static final int ANNOT_PROPERTY = 102;
    public static final int OTHER = -1;
    
}
